﻿using System;
using System.Collections.Generic;

namespace QAToolsAddin.Comparer {
    partial class Compare {
        private void SortOnIndexA(ref List<Match> array) {
            SortOnIndexA_recursive(ref array, 0, array.Count - 1);
        }

        private void SortOnIndexA_recursive(ref List<Match> array, int lower, int upper) {
            int l = lower, u = upper;
            int mid = (lower + upper) / 2;
            int index = array[mid].IndexA;
            while (l <= u) {
                while (array[l].IndexA < index) l++;
                while (index < array[u].IndexA) u--;
                if (l <= u) {
                    Match buffer = array[l];
                    array[l] = array[u];
                    array[u] = buffer;
                    l++; u--;
                }
            }
            if (lower < u) SortOnIndexA_recursive(ref array, lower, u);
            if (l < upper) SortOnIndexA_recursive(ref array, l, upper);
        }

        private void SortOnIndexB(ref List<Match> array) {
            SortOnIndexB_recursive(ref array, 0, array.Count - 1);
        }

        private void SortOnIndexB_recursive(ref List<Match> array, int lower, int upper) {
            int l = lower, u = upper;
            int mid = (lower + upper) / 2;
            int index = array[mid].IndexB;
            while (l <= u) {
                while (array[l].IndexB < index) l++;
                while (index < array[u].IndexB) u--;
                if (l <= u) {
                    Match buffer = array[l];
                    array[l] = array[u];
                    array[u] = buffer;
                    l++; u--;
                }
            }
            if (lower < u) SortOnIndexB_recursive(ref array, lower, u);
            if (l < upper) SortOnIndexB_recursive(ref array, l, upper);
        }

        private void SortOnHash(ref HashRow[] array) {
            SortOnHash_recursive(ref array, 0, array.Length - 1);
        }

        private void SortOnHash_recursive(ref HashRow[] array, int lower, int upper) {
            int l = lower, u = upper;
            int mid = (lower + upper) / 2;
            UInt32 index = array[mid].Hash;
            while (l <= u) {
                while (array[l].Hash < index)
                    l++;
                while (index < array[u].Hash)
                    u--;
                if (l <= u) {
                    HashRow buffer = array[l];
                    array[l] = array[u];
                    array[u] = buffer;
                    l++; u--;
                }
            }
            if (lower < u) SortOnHash_recursive(ref array, lower, u);
            if (l < upper) SortOnHash_recursive(ref array, l, upper);
        }

        private int[] GetSortedHashPtr(ref HashRow[] hashTabA) {
            int nbRow = hashTabA.Length;
            var sortedIndex = new int[hashTabA.LongLength];
            for (int i = 0; i < nbRow; i++)
                sortedIndex[i] = i;
            GetSortedPtr_Recursive(hashTabA, sortedIndex, 0, nbRow - 1);
            return sortedIndex;
        }

        private static void GetSortedPtr_Recursive(HashRow[] array, int[] ptr, int left, int rigth) {
            int l = left, r = rigth;
            int m = (left + rigth) / 2;
            int midPtr = ptr[m];
            uint midValue = array[midPtr].Hash;
            while (l <= r) {
                while (array[ptr[l]].Hash < midValue || (array[ptr[l]].Hash == midValue && ptr[l] < midPtr))
                    l++;
                while (midValue < array[ptr[r]].Hash || (array[ptr[r]].Hash == midValue && midPtr < ptr[r]))
                    r--;
                if (l <= r) {
                    int buffer = ptr[l];
                    ptr[l] = ptr[r];
                    ptr[r] = buffer;
                    l++; r--;
                }
            }
            if (left < r) GetSortedPtr_Recursive(array, ptr, left, r);
            if (l < rigth) GetSortedPtr_Recursive(array, ptr, l, rigth);
        }

        private int[] GetSortedHashPtr(ref HashCell[] hashTabA) {
            int nbRow = hashTabA.Length;
            var sortedIndex = new int[hashTabA.Length];
            for (int i = 0; i < nbRow; i++)
                sortedIndex[i] = i;
            GetSortedPtr_Recursive(hashTabA, sortedIndex, 0, nbRow - 1);
            return sortedIndex;
        }

        private static void GetSortedPtr_Recursive(HashCell[] array, int[] ptr, int left, int rigth) {
            int l = left, r = rigth;
            int m = (left + rigth) / 2;
            int midPtr = ptr[m];
            uint midValue = array[midPtr].Hash;
            while (l <= r) {
                while (array[ptr[l]].Hash < midValue || (array[ptr[l]].Hash == midValue && ptr[l] < midPtr))
                    l++;
                while (midValue < array[ptr[r]].Hash || (array[ptr[r]].Hash == midValue && midPtr < ptr[r]))
                    r--;
                if (l <= r) {
                    int buffer = ptr[l];
                    ptr[l] = ptr[r];
                    ptr[r] = buffer;
                    l++; r--;
                }
            }
            if (left < r) GetSortedPtr_Recursive(array, ptr, left, r);
            if (l < rigth) GetSortedPtr_Recursive(array, ptr, l, rigth);
        }

    }
}
